function [freq, info] = decode_single_frequency_wav(wav_fullname)
% Sound decoding algorithm for single-frequency encoding scheme.
%
% freq = the principal frequency
% info = debug information (peak, amplitude, peak2, amplitude2, ...
%

%% Decoding Agorithm

% BASIC
% Obtain the frequency components and select the first one.
%
%freqs = obtain_wav_frequency_components(wav_fullname);
%freq = (freqs(1)-500) * 5 /3000;
%info = freqs;


% % % % MULTIPLE-SLOTS
% % % % Split the acq into 5 slots and calculate the main freq in each one
% % % % Calculate the the most frequent 
% % % % Calcluate the mean of the values closer to the most frequent
% % % [y, Fs, nbits] = wavread(wav_fullname);
% % % total_time = length(y)/Fs;
% % % slot_duration = floor(10*total_time/5)/10;
% % % freq = calculateFFTbySlots(y,Fs, slot_duration);
% % % info = [];

% AMPLITUDE ENCODING
freqs=obtain_slot_frequencies(wav_fullname);
ff=find_message_frequencies(freqs);

freq = ff(1);
info = [ff -1 freqs];

%% Scaling
% Scaling 500-3500Hz => 0-5Volts
%freq = (freq-500) * 5 /3000;
%freq=freq2voltage(freq);

end

%% functions

function generateDiscreteFrequency()
discreteFrequenciesTable = [];
DF_RANGES = [500, 1200, 1700, 2000, 2300, 3400]; %// define the freq intervals
DF_LEVELS= [ 8,    7,    5,    3,    2]; %// define the number of levels in 100Hz in each interval
DF_NUMBER_INTERVALS =length(DF_RANGES); %// size of DF_RANGES array
DF_SIZE = 0;  %// number of discrete frequencies


counter = 1;
currentF = DF_RANGES(1);
for i=1: DF_NUMBER_INTERVALS-1
    f_increment =  floor(100.0/DF_LEVELS(i)) ;
    currentF = currentF + f_increment;
    maxF = DF_RANGES(i+1);
    while (currentF<=maxF) 
      discreteFrequenciesTable(counter) = currentF;
      counter=counter+1;
      currentF = currentF + f_increment;
    end
end
DF_SIZE = counter-1
for i=1: DF_SIZE
    disp( [ num2str(discreteFrequenciesTable(i)) ' ']);
end

end

function voltage = freq2voltage(frequency)
% single-discrete-frequency decoding
% 0-1023 u 0-5volts => v = u * 5 /1023;
% Freq bands:
%
% [500-1400) Hz => multiple of 5, u=(f-500)*2/5
%
% [1400-3500) Hz => multiple of 20, u=(f-1400)*2/20;

u = 0;

if (frequency<1400) 
    frequency = findNearestMultiple(frequency, 5);
%    u = (frequency-500) * 2 /5;
else
    frequency = findNearestMultiple(frequency, 20);
%    u = (frequency-1400) * 2 /20;
end

voltage = frequency;
%voltage = u* 5 /1023;

end

function nearest = findNearestMultiple(number, multiple)
% returns the closest integer to number that is multiple of multiple
    nearest = multiple * round(number/multiple);
end

function freq = calculateFFTbySlots(y,Fs, slot_duration)
% Splits the signal into slots, calculate the FFT in
% each one and returns the most frequent value (mode)

L = length(y);      % Length of signal
total_time = L/Fs;
NSlots = floor(total_time/slot_duration);
points_per_slot = floor(L/NSlots);
index = 1;
freqs = [];
for i=1:NSlots
    y_slot = y(index:index + points_per_slot-1); 
    components = calculateFFT(y_slot,Fs,1);
    freqs = [ freqs components(1)];
    %disp( ['>>>>freq: ' num2str( components(1) ) ]);
    index = index + points_per_slot;
end
freq = get_most_frequent(freqs);
end

function value=get_most_frequent(values)
% Obtain the most frequent value
    values100 = get_closer_values(values, 100);
    values10 = get_closer_values(values100, 10);
    if (length(values10)<1)
        value=0;
        return;
    end
    value = mean(values10);
end

function vals=get_closer_values(values, distance)
%Obtain values closer to the mode (<distance)
vals=[];
if (length(values)<1)
    return
end

mode_value = mode(round(values/distance))*distance;

% Select the values closer to the mode
for i=1:length(values)
    value = values(i);
    if ( abs(value-mode_value) < distance )
        vals = [vals value];
    end
end
end

%% amplitude-endoding algorithm

function freqs=obtain_slot_frequencies(wav_fullname)
[y, Fs, nbits] = wavread(wav_fullname);

% removing 0.1 seconds at the beginning and the end
npoints = floor(0.1 * Fs);
endpoint = length(y)-npoints;
y = y(npoints:endpoint);

total_time = length(y)/Fs;
L = length(y);
%Fs = 8072; %disp ( ['Fixed sampling frequency:' num2str(Fs)]);

slot_duration = 0.2;
points_per_slot = floor(slot_duration * Fs);
ff = [];
index =1;
while (index + points_per_slot < L)
    index = find_amplitude_step(y, Fs, index, slot_duration);
    if (index + points_per_slot > L-1)
        break
    end
    y_slot = y(index:index + points_per_slot-1);
    components = calculateFFT(y_slot,Fs,1);
    f = components(1);
    ff = [ff f ];
    index = index + floor(points_per_slot*0.7);
end
freqs = ff;
end


function position = find_amplitude_step(y, Fs, index, slot_duration)
% calculate when signal "steps up" from zero to non-zero

L = length(y);
slot_duration = slot_duration/32;
points_per_slot = floor(slot_duration * Fs);
position = index;
last_amplitude=1;
while (index + points_per_slot < L)
    y_slot = y(index:index + points_per_slot-1);
    amplitude = calculate_amplitude(y_slot);
    if (last_amplitude<1  && amplitude>0)
        position = index;
        break;
    end
    last_amplitude = amplitude;
    index = index + points_per_slot;
end
end

function amplitude = calculate_amplitude(y_slot)
%amplitude = mean(abs(y_slot));
counter = 0;
amplitude = 0;
zero_limit = 0.1;
L = length(y_slot);
for i=1:L
    if ( abs(y_slot(i)) > zero_limit )
        counter = counter +1;
    end
end
if counter > L/10
    amplitude = 1;
end
end

function ff=find_message_frequencies(freqs)
% expected ... start_f f1 f2 ... fn start_f f1
number_of_freq_slots = 6;
start_frequency = 3500;

ff(1)=0;
start_index = 1;
last_start_index = 1;
for i=1:length(freqs)
    if ( abs(freqs(i)- start_frequency) < 100 )
        start_index = i;
        break;
    end
    
end

end_index = start_index + number_of_freq_slots;
if end_index > length(freqs)
    end_index = length(freqs);
end

for i=start_index+1:end_index
    ff(i-start_index) = freqs(i);
end

end_index = start_index - number_of_freq_slots;
if end_index < 1
    end_index = 1;
end
for i=start_index-1:-1:end_index
    ff(number_of_freq_slots- start_index+i+1  )= freqs(i);
end



end
